-
Notifications
You must be signed in to change notification settings - Fork 416
Validate funding contributions reserves in splice_init
and splice_ack
handling
#4011
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
tankyleo
commented
Aug 14, 2025
👋 Thanks for assigning @TheBlueMatt as a reviewer! |
splice_ack
and splice_init
messagessplice_init
and splice_ack
messages
6d6b07c
to
93965c6
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4011 +/- ##
==========================================
- Coverage 88.74% 88.73% -0.02%
==========================================
Files 176 176
Lines 128638 128857 +219
Branches 128638 128857 +219
==========================================
+ Hits 114164 114339 +175
- Misses 11877 11922 +45
+ Partials 2597 2596 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
🔔 1st Reminder Hey @wpaulino! This PR has been waiting for your review. |
🔔 2nd Reminder Hey @wpaulino! This PR has been waiting for your review. |
On hold until splice-out PR gets in. |
🔔 3rd Reminder Hey @wpaulino! This PR has been waiting for your review. |
93965c6
to
d0023e3
Compare
lightning/src/sign/tx_builder.rs
Outdated
impl NextCommitmentStats { | ||
pub(crate) fn get_balances_including_fee_msat(&self) -> (Option<u64>, Option<u64>) { | ||
let holder_balance_incl_fee_msat = if self.is_outbound_from_holder { | ||
self.holder_balance_before_fee_msat |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this already have the anchor outputs value subtracted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
lightning/src/ln/channel.rs
Outdated
|
||
// TODO(splicing): Pre-check for reserve requirement | ||
// (Note: It should also be checked later at tx_complete) | ||
if their_funding_contribution.is_negative() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's also the case where we make a positive contribution and the counterparty does too, but a much larger one, bringing the reserve high enough that even after our contribution we still are not able to meet it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my reading of the spec, seems a party should only complain in cases where the counterparty's funding contribution is negative.
Did we want to be stricter than the spec here ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
// Reserve check on local commitment transaction | ||
|
||
let splice_local_commitment_stats = self.context.get_next_local_commitment_stats( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "next" naming is odd here because we're actually building an alternative version of the current commitment transaction
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed :) If a squint a little, the "next" commitment transaction will have different to_local, to_remote balances, that's the one we are validating here. As far as I see at this point, this "alternative" commitment transaction is the one we will sign "next" ?
This is from 3921 feel free to take a look.
👋 The first review has been submitted! Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer. |
d0023e3
to
835b67b
Compare
Rebase on merge-base (diff):
|
splice_init
and splice_ack
messagessplice_init
and splice_ack
handling
835b67b
to
453a211
Compare
Amend: (diff)
|
Rebasing now to fix conflict... |
453a211
to
9798f7a
Compare
As much as possible, we want to only mutate state once we are done with input validation. This also removes complaints when helper functions during validation take a `&self`.
As in `splice_init`, this helps clearly delineate `splice_ack` message validation from the subsequent state mutations. This is a code-move.
We will validate the reserve requirements on the new `FundingScope` in `validate_splice_contribution`.
`NextCommitmentStats` provides the commitment transaction fee as a separate value to assist with applying a multiplier on it in `can_accept_incoming_htlc`. Nonetheless in most cases, we want the balances to include the commitment transaction fee, so here we add a helper that gives us these balances.
Makes it consistent with `get_balances_including_fee`, itself added in the previous commit.
This applies to both `splice_init` and `splice_ack` messages. From BOLT 2: ``` - If `funding_contribution_satoshis` is negative and its absolute value is greater than the sending node's current channel balance: - MUST send a `warning` and close the connection or send an `error` and fail the channel. ``` Further down also: ``` If a side does not meet the reserve requirements, that's OK: but if they take funds out of the channel, they must ensure that they do meet them. If your peer adds a massive amount to the channel, then you only have to add more reserve if you want to contribute to the splice (and you can use `tx_remove_output` and/or `tx_remove_input` part-way through if this happens). ``` Therefore, we run the reserve check anytime the contribution is not equal to zero.
9798f7a
to
7a56757
Compare
lightning/src/sign/tx_builder.rs
Outdated
@@ -48,6 +49,26 @@ pub(crate) struct NextCommitmentStats { | |||
pub extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat: Option<u64>, | |||
} | |||
|
|||
impl NextCommitmentStats { | |||
pub(crate) fn get_balances_including_fee_msat(&self) -> (Option<u64>, Option<u64>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: for methods like this I really prefer we name them something that includes the order of the returned values. That way the callsite reads let (holder, counterparty) = x.get_holder_counterparty_balances_incl_fee_msat()
and it becaomes obvious if you invert the order. Alternatively, we can return Yet Another Struct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks will put this in #4032 likely
lightning/src/ln/channel.rs
Outdated
// TODO(splicing): Pre-check for reserve requirement | ||
// (Note: It should also be checked later at tx_complete) | ||
if their_funding_contribution != SignedAmount::ZERO { | ||
self.validate_their_funding_contribution_reserve(&splice_funding)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we're still missing validation for when we're the initiator and we contribute but the counterparty doesn't. Ideally the counterparty does reject a contribution we propose that would put us under the reserve, but we shouldn't be sending them invalid things in the first place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we're still missing validation for when we're the initiator and we contribute but the counterparty doesn't. Ideally the counterparty does reject a contribution we propose that would put us under the reserve, but we shouldn't be sending them invalid things in the first place.
Yes thank you, I'm planning to add a check in fn splice_channel
for the case where we are the initiator.
Did you have in mind to add a similar check on our own funding contribution in fn splice_init
in case we are not the initator ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should already be covered by validate_splice_init
? They must have something to contribute if they're the initiator (it doesn't look like we enforce this though we should), so we'd end up calling validate_their_funding_contribution_reserve
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should already be covered by validate_splice_init? They must have something to contribute if they're the initiator (it doesn't look like we enforce this though we should), so we'd end up calling validate_their_funding_contribution_reserve.
Right yes sounds like a quick check that splice_init.funding_contribution
is not zero on the receiver side of this message.
On the sending side, I'm thinking we'll also want to double check our own funding contribution before sending splice init.
lightning/src/ln/channel.rs
Outdated
|
||
/// Used to validate a negative `funding_contribution_satoshis` in `splice_init` and `splice_ack` messages. | ||
#[cfg(splicing)] | ||
fn validate_their_funding_contribution_reserve( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rename this since we're checking the reserve on both sides (remote balance on both local and remote commitments). Comment could use an update too.
Before sending a `splice_init`: * check that we can afford any negative contributions given our *current* channel balance. * check that we meet the v2 reserve requirement once our contribution is applied to the *next* funding scope.
5b205ec
to
9f4dc46
Compare